using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace GenerativeAgents.Core
{
    /// <summary>
    /// 行动计划器
    /// 负责根据目标、记忆和上下文生成具体的行动计划
    /// </summary>
    public class ActionPlanner
    {
        private Dictionary<string, PlanTemplate> planTemplates;
        private Dictionary<string, List<string>> goalActionMappings;
        
        public ActionPlanner()
        {
            InitializePlanTemplates();
            InitializeGoalActionMappings();
        }
        
        /// <summary>
        /// 初始化计划模板
        /// </summary>
        private void InitializePlanTemplates()
        {
            planTemplates = new Dictionary<string, PlanTemplate>();
            
            // 社交计划模板
            planTemplates["social_interaction"] = new PlanTemplate
            {
                templateId = "social_interaction",
                actionType = "social_interaction",
                defaultDuration = TimeSpan.FromMinutes(15),
                defaultPriority = 6,
                requiredConditions = new List<string> { "target_agent_available" },
                possibleLocations = new List<string> { "cafe", "park", "social_area" }
            };
            
            // 探索计划模板
            planTemplates["explore"] = new PlanTemplate
            {
                templateId = "explore",
                actionType = "explore",
                defaultDuration = TimeSpan.FromMinutes(30),
                defaultPriority = 4,
                requiredConditions = new List<string> { "not_in_conversation" },
                possibleLocations = new List<string> { "park", "unknown_area", "new_location" }
            };
            
            // 移动计划模板
            planTemplates["move"] = new PlanTemplate
            {
                templateId = "move",
                actionType = "move",
                defaultDuration = TimeSpan.FromMinutes(5),
                defaultPriority = 3,
                requiredConditions = new List<string> { "destination_accessible" },
                possibleLocations = new List<string> { "any" }
            };
            
            // 休息计划模板
            planTemplates["rest"] = new PlanTemplate
            {
                templateId = "rest",
                actionType = "rest",
                defaultDuration = TimeSpan.FromMinutes(20),
                defaultPriority = 5,
                requiredConditions = new List<string> { "energy_low" },
                possibleLocations = new List<string> { "home", "cafe", "quiet_area" }
            };
            
            // 工作计划模板
            planTemplates["work"] = new PlanTemplate
            {
                templateId = "work",
                actionType = "work",
                defaultDuration = TimeSpan.FromHours(2),
                defaultPriority = 7,
                requiredConditions = new List<string> { "work_location_available" },
                possibleLocations = new List<string> { "office", "cafe", "workplace" }
            };
            
            // 娱乐计划模板
            planTemplates["entertainment"] = new PlanTemplate
            {
                templateId = "entertainment",
                actionType = "entertainment",
                defaultDuration = TimeSpan.FromMinutes(45),
                defaultPriority = 4,
                requiredConditions = new List<string> { "free_time" },
                possibleLocations = new List<string> { "park", "entertainment_area", "cafe" }
            };
        }
        
        /// <summary>
        /// 初始化目标-行动映射
        /// </summary>
        private void InitializeGoalActionMappings()
        {
            goalActionMappings = new Dictionary<string, List<string>>();
            
            goalActionMappings["meet people"] = new List<string> { "social_interaction", "explore", "move" };
            goalActionMappings["explore environment"] = new List<string> { "explore", "move" };
            goalActionMappings["socialize"] = new List<string> { "social_interaction", "move" };
            goalActionMappings["learn"] = new List<string> { "explore", "social_interaction", "work" };
            goalActionMappings["relax"] = new List<string> { "rest", "entertainment", "move" };
            goalActionMappings["work"] = new List<string> { "work", "move" };
            goalActionMappings["rest"] = new List<string> { "rest", "move" };
            goalActionMappings["have fun"] = new List<string> { "entertainment", "social_interaction" };
        }
        
        /// <summary>
        /// 为目标创建计划
        /// </summary>
        public List<PlanItem> CreatePlansForGoal(string goal, List<MemoryNode> relevantMemories, 
            ILanguageModel languageModel, ScratchMemory scratchMemory)
        {
            var plans = new List<PlanItem>();
            
            try
            {
                // 找到匹配的行动类型
                var actionTypes = FindActionTypesForGoal(goal);
                
                foreach (var actionType in actionTypes.Take(2)) // 限制每个目标最多2个计划
                {
                    var plan = CreatePlanFromTemplate(actionType, goal, relevantMemories, languageModel, scratchMemory);
                    if (plan != null)
                    {
                        plans.Add(plan);
                    }
                }
                
                // 如果没有找到模板，创建通用计划
                if (plans.Count == 0)
                {
                    var genericPlan = CreateGenericPlan(goal, scratchMemory);
                    if (genericPlan != null)
                    {
                        plans.Add(genericPlan);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[ActionPlanner] Error creating plans for goal '{goal}': {ex.Message}");
            }
            
            return plans;
        }
        
        /// <summary>
        /// 为习惯创建计划
        /// </summary>
        public List<PlanItem> CreatePlansForHabits(List<string> habits, ScratchMemory scratchMemory)
        {
            var plans = new List<PlanItem>();
            
            try
            {
                foreach (var habit in habits.Take(1)) // 每次只处理一个习惯
                {
                    var plan = CreateHabitPlan(habit, scratchMemory);
                    if (plan != null)
                    {
                        plans.Add(plan);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[ActionPlanner] Error creating plans for habits: {ex.Message}");
            }
            
            return plans;
        }
        
        /// <summary>
        /// 创建机会计划
        /// </summary>
        public PlanItem CreateOpportunityPlan(MemoryNode observation, ScratchMemory scratchMemory)
        {
            try
            {
                // 基于观察内容确定机会类型
                var observationText = observation.description.ToLower();
                
                if (observationText.Contains("person") || observationText.Contains("agent"))
                {
                    // 社交机会
                    return CreateSocialOpportunityPlan(observation, scratchMemory);
                }
                else if (observationText.Contains("new") || observationText.Contains("interesting"))
                {
                    // 探索机会
                    return CreateExplorationOpportunityPlan(observation, scratchMemory);
                }
                else if (observationText.Contains("event") || observationText.Contains("activity"))
                {
                    // 活动机会
                    return CreateActivityOpportunityPlan(observation, scratchMemory);
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[ActionPlanner] Error creating opportunity plan: {ex.Message}");
            }
            
            return null;
        }
        
        /// <summary>
        /// 创建基于位置的计划
        /// </summary>
        public PlanItem CreateLocationBasedPlan(string locationName, ScratchMemory scratchMemory)
        {
            try
            {
                var locationLower = locationName.ToLower();
                
                if (locationLower.Contains("cafe") || locationLower.Contains("restaurant"))
                {
                    return new PlanItem
                    {
                        description = "Spend time at the cafe",
                        action = "social_interaction",
                        locationName = locationName,
                        targetLocation = scratchMemory.currentLocation,
                        scheduledTime = DateTime.Now.AddMinutes(UnityEngine.Random.Range(10, 60)),
                        estimatedDuration = TimeSpan.FromMinutes(30),
                        priority = 5,
                        motivation = "Enjoy the atmosphere and possibly meet people"
                    };
                }
                else if (locationLower.Contains("park") || locationLower.Contains("garden"))
                {
                    return new PlanItem
                    {
                        description = "Explore the park area",
                        action = "explore",
                        locationName = locationName,
                        targetLocation = scratchMemory.currentLocation,
                        scheduledTime = DateTime.Now.AddMinutes(UnityEngine.Random.Range(5, 30)),
                        estimatedDuration = TimeSpan.FromMinutes(25),
                        priority = 4,
                        motivation = "Enjoy nature and discover new areas"
                    };
                }
                else if (locationLower.Contains("library") || locationLower.Contains("study"))
                {
                    return new PlanItem
                    {
                        description = "Study or read at the library",
                        action = "work",
                        locationName = locationName,
                        targetLocation = scratchMemory.currentLocation,
                        scheduledTime = DateTime.Now.AddMinutes(UnityEngine.Random.Range(15, 45)),
                        estimatedDuration = TimeSpan.FromMinutes(60),
                        priority = 6,
                        motivation = "Learn something new and expand knowledge"
                    };
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[ActionPlanner] Error creating location-based plan: {ex.Message}");
            }
            
            return null;
        }
        
        /// <summary>
        /// 根据目标找到行动类型
        /// </summary>
        private List<string> FindActionTypesForGoal(string goal)
        {
            var goalLower = goal.ToLower();
            var actionTypes = new List<string>();
            
            foreach (var mapping in goalActionMappings)
            {
                if (goalLower.Contains(mapping.Key.ToLower()))
                {
                    actionTypes.AddRange(mapping.Value);
                }
            }
            
            // 如果没有找到匹配，使用默认行动类型
            if (actionTypes.Count == 0)
            {
                actionTypes.AddRange(new[] { "explore", "social_interaction" });
            }
            
            return actionTypes.Distinct().ToList();
        }
        
        /// <summary>
        /// 从模板创建计划
        /// </summary>
        private PlanItem CreatePlanFromTemplate(string actionType, string goal, List<MemoryNode> relevantMemories,
            ILanguageModel languageModel, ScratchMemory scratchMemory)
        {
            if (!planTemplates.TryGetValue(actionType, out var template))
            {
                return null;
            }
            
            try
            {
                var plan = new PlanItem
                {
                    description = GeneratePlanDescription(actionType, goal, languageModel),
                    action = template.actionType,
                    scheduledTime = DateTime.Now.AddMinutes(UnityEngine.Random.Range(5, 60)),
                    estimatedDuration = template.defaultDuration,
                    priority = template.defaultPriority,
                    motivation = goal,
                    isInterruptible = template.actionType != "work"
                };
                
                // 设置位置
                if (template.possibleLocations.Count > 0 && template.possibleLocations[0] != "any")
                {
                    var location = template.possibleLocations[UnityEngine.Random.Range(0, template.possibleLocations.Count)];
                    plan.locationName = location;
                    plan.targetLocation = DetermineLocationPosition(location, scratchMemory);
                }
                else
                {
                    plan.targetLocation = scratchMemory.currentLocation;
                    plan.locationName = scratchMemory.currentLocationName;
                }
                
                // 基于相关记忆调整计划
                AdjustPlanBasedOnMemories(plan, relevantMemories);
                
                return plan;
            }
            catch (Exception ex)
            {
                Debug.LogError($"[ActionPlanner] Error creating plan from template: {ex.Message}");
                return null;
            }
        }
        
        /// <summary>
        /// 生成计划描述
        /// </summary>
        private string GeneratePlanDescription(string actionType, string goal, ILanguageModel languageModel)
        {
            try
            {
                var templates = GetDescriptionTemplates(actionType);
                var template = templates[UnityEngine.Random.Range(0, templates.Count)];
                return string.Format(template, goal);
            }
            catch (Exception ex)
            {
                Debug.LogError($"[ActionPlanner] Error generating plan description: {ex.Message}");
                return $"Perform {actionType} to achieve {goal}";
            }
        }
        
        /// <summary>
        /// 获取描述模板
        /// </summary>
        private List<string> GetDescriptionTemplates(string actionType)
        {
            var templates = new Dictionary<string, List<string>>
            {
                ["social_interaction"] = new List<string>
                {
                    "Meet and talk with someone to {0}",
                    "Have a conversation related to {0}",
                    "Interact with others about {0}",
                    "Socialize and discuss {0}"
                },
                ["explore"] = new List<string>
                {
                    "Explore the area to {0}",
                    "Discover new places while pursuing {0}",
                    "Wander around to {0}",
                    "Investigate the environment for {0}"
                },
                ["move"] = new List<string>
                {
                    "Go to a location to {0}",
                    "Travel to {0}",
                    "Move to achieve {0}",
                    "Head somewhere for {0}"
                },
                ["rest"] = new List<string>
                {
                    "Take a break to {0}",
                    "Rest and think about {0}",
                    "Relax while considering {0}",
                    "Take time to recharge for {0}"
                },
                ["work"] = new List<string>
                {
                    "Work on tasks related to {0}",
                    "Focus on activities for {0}",
                    "Engage in productive work toward {0}",
                    "Dedicate time to {0}"
                },
                ["entertainment"] = new List<string>
                {
                    "Enjoy entertainment while thinking about {0}",
                    "Have fun and consider {0}",
                    "Engage in leisure activities for {0}",
                    "Relax and enjoy time pursuing {0}"
                }
            };
            
            return templates.GetValueOrDefault(actionType, new List<string> { "Perform activity to {0}" });
        }
        
        /// <summary>
        /// 创建通用计划
        /// </summary>
        private PlanItem CreateGenericPlan(string goal, ScratchMemory scratchMemory)
        {
            return new PlanItem
            {
                description = $"Work toward: {goal}",
                action = "explore",
                targetLocation = scratchMemory.currentLocation,
                locationName = scratchMemory.currentLocationName,
                scheduledTime = DateTime.Now.AddMinutes(UnityEngine.Random.Range(10, 30)),
                estimatedDuration = TimeSpan.FromMinutes(20),
                priority = 3,
                motivation = goal
            };
        }
        
        /// <summary>
        /// 创建习惯计划
        /// </summary>
        private PlanItem CreateHabitPlan(string habit, ScratchMemory scratchMemory)
        {
            var habitLower = habit.ToLower();
            
            if (habitLower.Contains("break") || habitLower.Contains("rest"))
            {
                return new PlanItem
                {
                    description = $"Habit: {habit}",
                    action = "rest",
                    targetLocation = scratchMemory.currentLocation,
                    locationName = scratchMemory.currentLocationName,
                    scheduledTime = DateTime.Now.AddMinutes(UnityEngine.Random.Range(30, 90)),
                    estimatedDuration = TimeSpan.FromMinutes(15),
                    priority = 5,
                    motivation = "Maintain healthy habits"
                };
            }
            else if (habitLower.Contains("greet") || habitLower.Contains("social"))
            {
                return new PlanItem
                {
                    description = $"Habit: {habit}",
                    action = "social_interaction",
                    targetLocation = scratchMemory.currentLocation,
                    locationName = scratchMemory.currentLocationName,
                    scheduledTime = DateTime.Now.AddMinutes(UnityEngine.Random.Range(5, 20)),
                    estimatedDuration = TimeSpan.FromMinutes(10),
                    priority = 4,
                    motivation = "Follow social habits"
                };
            }
            
            return null;
        }
        
        /// <summary>
        /// 创建社交机会计划
        /// </summary>
        private PlanItem CreateSocialOpportunityPlan(MemoryNode observation, ScratchMemory scratchMemory)
        {
            return new PlanItem
            {
                description = $"Social opportunity: {observation.description}",
                action = "social_interaction",
                targetLocation = observation.location,
                locationName = observation.locationName,
                scheduledTime = DateTime.Now.AddMinutes(UnityEngine.Random.Range(1, 10)),
                estimatedDuration = TimeSpan.FromMinutes(15),
                priority = 7, // 高优先级，因为是及时机会
                motivation = "Take advantage of social opportunity"
            };
        }
        
        /// <summary>
        /// 创建探索机会计划
        /// </summary>
        private PlanItem CreateExplorationOpportunityPlan(MemoryNode observation, ScratchMemory scratchMemory)
        {
            return new PlanItem
            {
                description = $"Explore: {observation.description}",
                action = "explore",
                targetLocation = observation.location,
                locationName = observation.locationName,
                scheduledTime = DateTime.Now.AddMinutes(UnityEngine.Random.Range(5, 15)),
                estimatedDuration = TimeSpan.FromMinutes(20),
                priority = 6,
                motivation = "Investigate interesting observation"
            };
        }
        
        /// <summary>
        /// 创建活动机会计划
        /// </summary>
        private PlanItem CreateActivityOpportunityPlan(MemoryNode observation, ScratchMemory scratchMemory)
        {
            return new PlanItem
            {
                description = $"Participate in: {observation.description}",
                action = "entertainment",
                targetLocation = observation.location,
                locationName = observation.locationName,
                scheduledTime = DateTime.Now.AddMinutes(UnityEngine.Random.Range(2, 8)),
                estimatedDuration = TimeSpan.FromMinutes(30),
                priority = 6,
                motivation = "Join interesting activity"
            };
        }
        
        /// <summary>
        /// 确定位置坐标
        /// </summary>
        private Vector3 DetermineLocationPosition(string locationName, ScratchMemory scratchMemory)
        {
            // 简化实现：基于位置名称生成大致坐标
            var locationMap = new Dictionary<string, Vector3>
            {
                ["cafe"] = new Vector3(-20, 0, 0),
                ["park"] = new Vector3(20, 0, 0),
                ["social_area"] = new Vector3(0, 0, 10),
                ["office"] = new Vector3(-10, 0, -10),
                ["library"] = new Vector3(10, 0, -10),
                ["entertainment_area"] = new Vector3(0, 0, 20),
                ["home"] = new Vector3(0, 0, -20),
                ["workplace"] = new Vector3(-15, 0, -5)
            };
            
            if (locationMap.TryGetValue(locationName, out var position))
            {
                // 添加一些随机偏移
                var offset = UnityEngine.Random.insideUnitSphere * 5f;
                offset.y = 0;
                return position + offset;
            }
            
            // 默认返回当前位置附近的随机位置
            var randomOffset = UnityEngine.Random.insideUnitSphere * 10f;
            randomOffset.y = 0;
            return scratchMemory.currentLocation + randomOffset;
        }
        
        /// <summary>
        /// 基于记忆调整计划
        /// </summary>
        private void AdjustPlanBasedOnMemories(PlanItem plan, List<MemoryNode> relevantMemories)
        {
            if (relevantMemories == null || relevantMemories.Count == 0)
                return;
            
            try
            {
                // 基于记忆的重要性调整优先级
                var avgImportance = relevantMemories.Average(m => m.poignancy);
                if (avgImportance > 7)
                {
                    plan.priority = Math.Min(10, plan.priority + 1);
                }
                else if (avgImportance < 4)
                {
                    plan.priority = Math.Max(1, plan.priority - 1);
                }
                
                // 基于社交记忆调整社交计划
                if (plan.action == "social_interaction")
                {
                    var socialMemories = relevantMemories.Where(m => m.type == MemoryType.Chat || m.type == MemoryType.Event);
                    foreach (var memory in socialMemories.Take(3))
                    {
                        if (!string.IsNullOrEmpty(memory.subject) && !plan.involvedAgents.Contains(memory.subject))
                        {
                            plan.involvedAgents.Add(memory.subject);
                        }
                    }
                }
                
                // 基于位置记忆调整位置
                var locationMemories = relevantMemories.Where(m => !string.IsNullOrEmpty(m.locationName));
                if (locationMemories.Any() && string.IsNullOrEmpty(plan.locationName))
                {
                    var bestLocation = locationMemories.OrderByDescending(m => m.poignancy).First();
                    plan.locationName = bestLocation.locationName;
                    plan.targetLocation = bestLocation.location;
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[ActionPlanner] Error adjusting plan based on memories: {ex.Message}");
            }
        }
    }
    
    /// <summary>
    /// 计划模板
    /// </summary>
    [System.Serializable]
    public class PlanTemplate
    {
        public string templateId;
        public string actionType;
        public TimeSpan defaultDuration;
        public int defaultPriority;
        public List<string> requiredConditions;
        public List<string> possibleLocations;
        
        public PlanTemplate()
        {
            requiredConditions = new List<string>();
            possibleLocations = new List<string>();
        }
    }
}